<?php

namespace app\service;

use app\core\Constant;
use app\core\exception\BusinessException;
use app\core\Request;
use app\core\Service;
use app\model\SysApp;
use app\model\SysMenu;
use app\model\SysPermission;
use app\model\SysRole;
use app\model\SysRoleDept;
use app\model\SysRoleMenu;
use app\model\SysRolePerm;
use app\model\SysUserRole;
use think\facade\Cache;
use think\facade\Db;

/**
 * @extends Service<RoleService>
 */
class RoleService extends Service
{

    public function selectRoles()
    {
        return SysRole::field("role_id, role_name")
            ->where('status', Constant::STATUS_NORMAL)
            ->select()->toArray();
    }

    public function save($data, $role_id = null)
    {
        $saveData = [
            'role_name' => $data['role_name'],
            'role_key' => $data['role_key'],
            'role_sort' => $data['role_sort'] ?? 99,
            'data_scope' => $data['data_scope'] ?? Constant::DATA_SCOPE_SELF,
            'status' => $data['status'] ?? '0',
            'remark' => $data['remark'] ?? null
        ];

        Db::startTrans();
        try {
            if (!empty($role_id)) {
                $role = SysRole::where('role_id', $role_id)->find();
                if (!$role) {
                    throw new BusinessException('角色不存在');
                }
                $role->save($saveData);
                // 删除角色关联的菜单和部门权限
                SysRoleMenu::where('role_id', $role->role_id)->delete();
                SysRolePerm::where('role_id', $role->role_id)->delete();
                SysRoleDept::where('role_id', $role->role_id)->delete();
            } else {
                if (SysRole::where('role_key', $saveData['role_key'])->find()) {
                    throw new BusinessException('角色标识已存在');
                }
                $role = SysRole::create($saveData);
                if (!$role) {
                    throw new BusinessException('创建失败');
                }
            }
            $menu_ids = [];
            $perm_ids = [];
            $apps = AppServiec::invoke()->select();
            foreach ($apps as $item){
                $menu_ids = array_merge($menu_ids, $data['menus'][$item['app_key']] ?? []);
                $perm_ids = array_merge($perm_ids, $data['perms'][$item['app_key']] ?? []);
            }
            // 关联角色菜单
            $menuIds = $menu_ids;
            foreach ($menuIds as $menuId) {
                SysRoleMenu::create([
                    'role_id' => $role->role_id,
                    'menu_id' => $menuId
                ]);
            }
            // 关联角色接口
            $permIds = $perm_ids;
            foreach ($permIds as $permId) {
                SysRolePerm::create([
                    'role_id' => $role->role_id,
                    'permission_id' => $permId
                ]);
            }
            // 关联角色部门权限
            if ($saveData['data_scope'] == Constant::DATA_SCOPE_DIV) {
                $deptIds = $data['dept_ids'] ?? [];
                foreach ($deptIds as $deptId) {
                    SysRoleDept::create([
                        'role_id' => $role->role_id,
                        'dept_id' => $deptId
                    ]);
                }
            }
            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            throw new BusinessException($e->getMessage());
        }

        // 删除菜单缓存
        Cache::delete("menus");
    }

    public function list($page = 1, $limit = 10, $searchQuery = null)
    {
        $list = SysRole::where(function ($q) use ($searchQuery) {
            if (!empty($searchQuery['role_name'])) {
                $q = $q->where('role_name', $searchQuery['role_name']);
            }
            if (!empty($searchQuery['role_key'])) {
                $q = $q->where('role_key', $searchQuery['role_key']);
            }
            if (!empty($searchQuery['status'])) {
                $q->where('status', $searchQuery['status']);
            }
        });

        $total = $list->count();
        $list = $list
            ->order('role_sort desc')
            ->page($page, $limit)->select()->toArray();

        return ['total' => $total, 'list' => $list];
    }

    public function info($role_id)
    {
        $role = SysRole::find($role_id);
        if (!$role) {
            throw new BusinessException('角色不存在');
        }

        $apps = AppServiec::invoke()->select();
        $menus = [];
        $perms = [];

        foreach ($apps as $app){
            $menu_ids = SysMenu::where('app_key', $app['app_key'])
                ->field('menu_id')
                ->buildSql();
            $perm_ids = SysPermission::where('app_key', $app['app_key'])
                ->field('permission_id')
                ->buildSql();
            $menus[$app['app_key']] = SysRoleMenu::where('role_id', $role_id)
                ->where("menu_id", "exp", "in $menu_ids")
                ->column("menu_id");
            $perms[$app['app_key']] = SysRolePerm::where('role_id', $role_id)
                ->where("permission_id", "exp", "in $perm_ids")
                ->column("permission_id");
        }

        $role['menus'] = $menus;
        $role['perms'] = $perms;
        $role['dept_ids'] = SysRoleDept::where('role_id', $role_id)->column("dept_id");

        return $role->toArray();
    }

    public function del($role_id)
    {
        $role = SysRole::find($role_id);
        if (!$role) {
            throw new BusinessException('角色不存在');
        }

        // 判断是否存在用户关联角色
        if (SysUserRole::where('role_id', $role_id)->find()) {
            throw new BusinessException('存在用户关联该角色，暂时无法删除');
        }

        Db::startTrans();
        try {
            $role->delete();
            // 删除角色关联的菜单和部门权限
            SysRoleMenu::where('role_id', $role->role_id)->delete();
            SysRoleDept::where('role_id', $role->role_id)->delete();
            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            throw new BusinessException($e->getMessage());
        }
    }
}